package com.jprocms.module.cms.config;

import com.jpro.module.infra.api.config.ConfigApi;
import com.jpro.module.system.api.dict.DictDataApi;
import com.jprocms.module.cms.cache.MyRedisHelper;
import com.jprocms.module.cms.controller.directive.*;
import com.jprocms.module.cms.es.service.ContentEsService;
import com.jprocms.module.cms.service.channel.ChannelService;
import com.jprocms.module.cms.service.comment.CommentService;
import com.jprocms.module.cms.service.content.ContentRelateService;
import com.jprocms.module.cms.service.content.ContentService;
import com.jprocms.module.cms.service.content.TagService;
import com.jprocms.module.cms.service.guestbook.GuestbookService;
import com.jprocms.module.cms.service.investigate.InvestigateService;
import com.jprocms.module.cms.service.link.LinkService;
import com.jprocms.module.cms.service.site.SiteService;
import com.jprocms.module.cms.service.sysword.SysWordService;
import com.jprocms.module.cms.service.vote.VoteService;
import com.jprocms.module.cms.util.*;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.URLTemplateLoader;
import lombok.extern.slf4j.Slf4j;
import no.api.freemarker.java8.Java8ObjectWrapper;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;
import java.net.URL;
import java.util.Objects;

/**
 * @author jprocms
 */
@Configuration
@Slf4j
public class FreemarkerConfig implements InitializingBean {

    @Autowired
    private FreeMarkerConfigurer configurer;

    @Resource
    private TplConfigProperties tplConfigProperties;

    private final TagService tagService;
    private final SiteService siteService;
    private final ContentService contentService;
    private ContentRelateService contentRelateService;
    private final ChannelService channelService;
    private final DictDataApi dictDataApi;
    private ContentEsService contentEsService;
    private GuestbookService guestbookService;
    private LinkService linkService;
    private VoteService voteService;
    private InvestigateService investigateService;

    private MyRedisHelper redisHelper;

    private SysWordService wordService;

    private CommentService commentService;

    private ConfigApi configApi;
    private JproProperties jproProperties;

    public FreemarkerConfig(TagService tagService, VoteService voteService, SiteService siteService, ContentService contentService,
                            ChannelService channelService, LinkService linkService, ContentRelateService contentRelateService,
                            DictDataApi dictDataApi, ContentEsService contentEsService, GuestbookService guestbookService,
                            InvestigateService investigateService, SysWordService wordService, MyRedisHelper redisHelper,
                            CommentService commentService, ConfigApi configApi, JproProperties jproProperties) {
        this.tagService = tagService;
        this.siteService = siteService;
        this.contentService = contentService;
        this.channelService = channelService;
        this.contentRelateService = contentRelateService;
        this.dictDataApi = dictDataApi;
        this.contentEsService = contentEsService;
        this.guestbookService = guestbookService;
        this.linkService = linkService;
        this.voteService = voteService;
        this.investigateService = investigateService;
        this.wordService = wordService;
        this.redisHelper = redisHelper;
        this.commentService = commentService;
        this.configApi = configApi;
        this.jproProperties = jproProperties;
    }

    @PostConstruct
    public FreeMarkerConfigurer freeMarkerConfigurer() throws Exception {
        FreeMarkerConfigurer freeMarkerConfigurer = configurer;
        freemarker.template.Configuration cfg = configurer.getConfiguration();
        freeMarkerConfigurer.setDefaultEncoding("UTF-8");
        if (Objects.equals(tplConfigProperties.getType(), "local")) {
            TplLocalConfigProperties tplLocalConfigProperties = tplConfigProperties.getTplLocalConfig();
            log.info("local path:{}", tplLocalConfigProperties.getPath());
            cfg.setTemplateLoader(new FileTemplateLoader(new File(tplLocalConfigProperties.getPath())));
        } else if (Objects.equals(tplConfigProperties.getType(), "ftp")) {
            TplFtpConfigProperties tplFtpConfigProperties = tplConfigProperties.getTplFtpConfig();
            URLTemplateLoader urlTemplateLoader = new URLTemplateLoader() {
                @Override
                protected URL getURL(String name) {
                    name = name.replace("_zh", "").replace("_CN", "");
                    URL url = tplFtpConfigProperties.getUrl(name);
                    return url;
                }
            };
            cfg.setTemplateLoader(urlTemplateLoader);
        }
        return freeMarkerConfigurer;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        freemarker.template.Configuration cfg = configurer.getConfiguration();
        cfg.setObjectWrapper(new Java8ObjectWrapper(freemarker.template.Configuration.VERSION_2_3_31));
        cfg.setSharedVariable("ZContent", new ContentDirective(contentService));
        cfg.setSharedVariable("ZContentList", new ContentListDirective(contentService, channelService, jproProperties));
        cfg.setSharedVariable("ZContentPage", new ContentPageDirective(contentService, channelService, jproProperties));
        cfg.setSharedVariable("ZContentRelateList", new ContentRelateListDirective(contentRelateService));
        cfg.setSharedVariable("ZContentSide", new ContentSideDirective(contentService));
        cfg.setSharedVariable("ZSite", new SiteDirective(siteService));
        cfg.setSharedVariable("ZSiteList", new SiteListDirective(siteService));
        cfg.setSharedVariable("ZDictList", new DictListDirective(dictDataApi, redisHelper));
        cfg.setSharedVariable("ZTagList", new TagListDirective(tagService));
        cfg.setSharedVariable("ZTagPage", new TagPageDirective(tagService));
        cfg.setSharedVariable("ZChannelList", new ChannelListDirective(channelService));
        cfg.setSharedVariable("ZChannel", new ChannelDirective(channelService));
        cfg.setSharedVariable("ZContentSearchPage", new ContentSearchPageDirective(channelService, contentEsService, wordService));
        cfg.setSharedVariable("ZGuestbookList", new GuestbookListDirective(guestbookService));
        cfg.setSharedVariable("ZGuestbookPage", new GuestbookPageDirective(guestbookService));
        cfg.setSharedVariable("ZLinkList", new LinkListDirective(linkService));
        cfg.setSharedVariable("ZVoteList", new VoteListDirective(voteService));
        cfg.setSharedVariable("ZVotePage", new VotePageDirective(voteService));
        cfg.setSharedVariable("ZVote", new VoteDirective(voteService));
        cfg.setSharedVariable("ZInvestigate", new InvestigateDirective(investigateService));
        cfg.setSharedVariable("ZInvestigateList", new InvestigateListDirective(investigateService));
        cfg.setSharedVariable("ZInvestigatePage", new InvestigatePageDirective(investigateService));
        cfg.setSharedVariable("ZCommentList", new CommentListDirective(commentService));
        cfg.setSharedVariable("ZCommentPage", new CommentPageDirective(commentService));
        cfg.setSharedVariable("ZConfig", new ConfigDirective(configApi));


        cfg.setSharedVariable("ZUrl", new UrlDirective());
        cfg.setSharedVariable("ZPage", new PageResolve(FrontContextUtil.PAGE));
        cfg.setSharedVariable("ZParamsJoin", new FreemarkerParamsJoin(FrontContextUtil.PAGE));
        cfg.setSharedVariable("ZFormat", new FreemarkerTimeFormat());
        cfg.setSharedVariable("ZSubstring", new FreemarkerSubstring());
    }
}
